package com.gitee.wsl.android.ui.recyclerView.adapter.viewholder

import android.util.SparseArray
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.recyclerview.widget.RecyclerView
import com.gitee.wsl.android.ui.recyclerView.adapter.AdapterConfig

/**
 * 定义
 */

interface ViewHolderFactory<VH : RecyclerView.ViewHolder> {
    fun getSupportType():Int
    fun getViewHolder(parent: ViewGroup, layoutInflater: LayoutInflater): VH
}


internal typealias CreateViewBingHandler<VIEW_BIND> = View.() -> VIEW_BIND

class ViewHolderFactoryBuilderConfig<T : Any,AR: com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T>,VIEW_BIND>:ViewHolderBuilderConfig(){
    var viewBinderCreateHandler: CreateViewBingHandler<VIEW_BIND>?=null
    var viewHolderWithViewBindingHandler:ViewHolderBindAction<T,AR,VIEW_BIND>?=null
}

open class ViewHolderBuilderConfig{
    var type:Int = AdapterConfig.LAYOUT_TYPE_DEFAULT
    var layoutResId:Int = 0
}

interface ViewHolderFactoryBuilderScope<T : Any,AR: com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T>,VIEW_BIND>{
    fun createBindView(layoutResId:Int,type:Int = AdapterConfig.LAYOUT_TYPE_DEFAULT,viewBinderCreateHandler:View.() -> VIEW_BIND)

    fun bindViewHolder(handler:(viewBinding: VIEW_BIND, position: Int, payloads: List<Any>, item:T?, config: ViewHolderConfig<T , AR>)->Unit)

    fun bindViewHolder(handler:ViewHolderBindAction<T,AR,VIEW_BIND>)
}

interface ViewHolderFactoryBuilderScopeAdv<T : Any,AR: com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T>,VIEW_BIND>:ViewHolderFactoryBuilderScope<T,AR,VIEW_BIND>{
    fun config(configViewHolder:ViewHolderBuilderConfig.()->Unit)
    fun createBindView(viewBinderCreateHandler:View.() -> VIEW_BIND)
}

open class ViewHolderFactoryBuilder<T : Any,AR: com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T>,VIEW_BIND>:ViewHolderFactoryBuilderScopeAdv<T,AR,VIEW_BIND>{
    val config = ViewHolderFactoryBuilderConfig<T,AR,VIEW_BIND>()

    override fun config(configViewHolder: ViewHolderBuilderConfig.() -> Unit) {
        configViewHolder(config)
    }

    override fun createBindView(
        layoutResId: Int,
        type: Int,
        viewBinderCreateHandler: View.() -> VIEW_BIND
    ) {
        config.type=type
        config.layoutResId=layoutResId
        createBindView(viewBinderCreateHandler)
    }

    override fun createBindView(viewBinderCreateHandler: CreateViewBingHandler<VIEW_BIND>) {
        config.viewBinderCreateHandler=viewBinderCreateHandler
    }

    override fun bindViewHolder(handler: ViewHolderBindAction<T, AR, VIEW_BIND>) {
        config.viewHolderWithViewBindingHandler=handler
    }

    override fun bindViewHolder(handler: BindViewHolderWithViewBindingHandler<T, AR, VIEW_BIND>) {
        bindViewHolder(ViewHolderBindAction{ parent, position, payloads, item, config -> handler(parent,position, payloads, item, config) })
    }

    fun build(): DefaultViewHolderFactoryImp<T, AR> {
        return DefaultViewHolderFactoryImp.build(config)
    }
}


/**
 * 实现
 */

abstract class DefaultBaseViewHolderFactoryImp<T : Any, AR : com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T>,BIND_VIEW>(val type: Int, val bindCallbacks:ViewHolderBindAction<T,AR,BIND_VIEW>) :
    ViewHolderFactory<DefaultBaseViewHolder<T, AR,BIND_VIEW>> {
    abstract fun createHolderView(parent: ViewGroup, layoutInflater: LayoutInflater): BIND_VIEW

    override fun getSupportType(): Int {
        return type
    }
}

open class DefaultViewHolderFactoryImp<T : Any,AR: com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T>>(type:Int, @LayoutRes val layoutId:Int, bindCallbacks: ViewHolderAction<T,AR>):
    DefaultBaseViewHolderFactoryImp<T, AR,View>(type,bindCallbacks) {
    override fun getViewHolder(parent: ViewGroup, layoutInflater: LayoutInflater): DefaultViewHolder<T,AR> {
        val view = createHolderView(parent, layoutInflater)
        return DefaultViewHolderBuilder(view, bindCallbacks).build()
    }

    override fun createHolderView(parent: ViewGroup, layoutInflater: LayoutInflater): View {
        return layoutInflater.inflate(layoutId, parent,false)
    }

    companion object{
        fun <T : Any,AR: com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T>> build(type:Int, @LayoutRes layoutId:Int, bindCallbacks: ViewHolderAction<T,AR>): DefaultViewHolderFactoryImp<T, AR> {
            return DefaultViewHolderFactoryImp(type,layoutId,bindCallbacks)
        }

        fun <T : Any,AR: com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T>> build(type:Int, @LayoutRes layoutId:Int, bindCallbacks: BindViewHolderHandler<T,AR>): DefaultViewHolderFactoryImp<T, AR> {
            return DefaultViewHolderFactoryImp(type,layoutId
            ) { parent, position, payloads, item, config ->
                bindCallbacks(
                    parent,
                    position,
                    payloads,
                    item,
                    config
                )
            }
        }

        fun <T : Any,AR: com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T>,VIEW_BIND> build(viewHolderBuilderConfig:ViewHolderFactoryBuilderConfig<T ,AR,VIEW_BIND>): DefaultViewHolderFactoryImp<T, AR> {

            if(viewHolderBuilderConfig.viewBinderCreateHandler==null || viewHolderBuilderConfig.viewHolderWithViewBindingHandler==null)
                throw IllegalArgumentException("config must all set")

            return build(viewHolderBuilderConfig.type,
                viewHolderBuilderConfig.layoutResId,
                viewHolderBuilderConfig.viewHolderWithViewBindingHandler!!,
                viewHolderBuilderConfig.viewBinderCreateHandler!!
            )
        }

        fun <T : Any,AR: com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T>,VIEW_BIND> build(type:Int, @LayoutRes layoutId:Int, bindCallbacks: ViewHolderBindAction<T,AR,VIEW_BIND>, viewBindCreate:CreateViewBingHandler<VIEW_BIND>): DefaultViewHolderFactoryImp<T, AR> {
            return build(type, layoutId, DefaultViewHolderBindTranAction(viewBindCreate,bindCallbacks))
        }

        fun <T : Any,AR: com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T>,VIEW_BIND> build(type:Int, @LayoutRes layoutId:Int, bindCallbacks: ViewHolderBindTranAction<T,AR,VIEW_BIND>): DefaultViewHolderFactoryImp<T, AR> {
            return DefaultViewHolderFactoryImp(type,layoutId,ViewHolderBindActionWarp(bindCallbacks))
        }

    }
}

/**
 * 管理
 */

interface ViewHolderFactoryManager<VHF : ViewHolderFactory<out RecyclerView.ViewHolder>> {
    fun register(type: Int, item: VHF): Boolean
    operator fun get(type: Int): VHF
    fun contains(type: Int): Boolean
    fun clear()
}

class DefaultViewHolderFactoryManager<VHF : ViewHolderFactory<out RecyclerView.ViewHolder>> : ViewHolderFactoryManager<VHF> {
    private val typeInstances = SparseArray<VHF>()
    override fun register(type: Int, item: VHF): Boolean {
        if (typeInstances.indexOfKey(type) < 0) {
            typeInstances.put(type, item)
            return true
        }
        return false
    }
    override fun get(type: Int): VHF {
        return typeInstances.get(type)
    }
    override fun contains(type: Int) = typeInstances.indexOfKey(type) >= 0
    override fun clear() {
        typeInstances.clear()
    }
}
